﻿package jokers{
	import jokers.*;
	import flash.display.MovieClip;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
    public class JMatrix { 
		public static const WIDTH:int = 480;
		public static const HEIGHT:int = 800;
		public static const FPS:int = 30;
		public static const BAC_DES:int = 100;
		
		private static var jmatrix:JMatrix;
		
		private var layout_bac:MovieClip;
		private var layout_crystal:MovieClip;
		private var layout_effect:MovieClip;
		private var layout_top:MovieClip;
		private var layout_event:MovieClip;
		
		private var matrix:Array;
		private var bacs:Array;
		
		private var hasRefreshed:Boolean = false;
		
		private var func_win:Function;
		private var func_fail:Function;
		
		private var w:int;
		private var h:int;
		
		private var scale:Number;
		
		public var des:int;
		private var timer:JTimer;
		
		private var target:MovieClip = null;
		private var mouseIsDown:Boolean = false;
		
		//init - 获取单件
		public static function getInstance():JMatrix{
			return jmatrix;
		}
		
		//init - 初始化对象
		public function JMatrix(w:int = 8,h:int = 8){
			this.w = w;
			this.h = h;
			
			jmatrix = this;
		}
		
		//para - 获取属性
		public function get width():int{
			return w;
		}
		
		public function get height():int{
			return h;
		}
		
		public function get per():Number{
			return scale;
		}
		
		public function get effctStage():MovieClip{
			return layout_effect;
		}
		
		public function get topStage():MovieClip{
			return layout_top;
		}
		
		public function get crystalStage():MovieClip{
			return layout_crystal;
		}
		
		public function getMatrix():Array{
			return matrix;
		}
		
		//init - 初始化系统&界面
		public function init(func_win:Function,func_fail:Function):void{
			//--function
			this.func_win = func_win;
			this.func_fail = func_fail;
			//--Timer
			timer = new JTimer();
			timer.setTimerFunc(refreshSys);
			//--UI
			des = WIDTH / w;
			
			//--Btn listener
			JPara.btn_search.addEventListener(MouseEvent.CLICK,clickSearch);
			JPara.btn_refresh.addEventListener(MouseEvent.CLICK,clickRefresh);
			
			drawBac();
			
			layout_crystal = new MovieClip();
			JPara.stage.addChild(layout_crystal);
			
			layout_effect = new MovieClip();
			JPara.stage.addChild(layout_effect);
			
			layout_top = new MovieClip();
			JPara.stage.addChild(layout_top);
			
			layout_event = new MovieClip();
			JPara.stage.addChild(layout_event);
			
			var cm:Array = JAlgorithm.getMatrix(w,h,JPara.crystalNum);
			
			scale = JCrystal.CRYSTAL_DES * w / HEIGHT;
			
			matrix = new Array();
			
			var id:int = 0;
			bacs = new Array();
			
			for (var x:int = 0; x < w; x++)
			{
				matrix[x] = new Array();
				for (var y:int = 0; y < h; y++)
				{
					var c:MovieClip = JCrystal.getCrystal(cm[x][y]);
					c.scaleX = scale;
					c.scaleY = scale;
					c.x = x * des + des/2;
					c.y = y * des + des/2;
					
					c.alpha = 0;
					
					matrix[x][y] = c;
					
					var tc:MovieClip = new CRect();
					tc.width = des;
					tc.height = des;
					tc.x = x*des;
					tc.y = y*des;
					tc.xx = x;
					tc.yy = y;
					tc.addEventListener(MouseEvent.MOUSE_DOWN,cclick);
					tc.addEventListener(MouseEvent.MOUSE_OUT,cout);
					tc.addEventListener(MouseEvent.MOUSE_UP,cup);
					
					bacs[id] = tc;
					id++;
					
					layout_crystal.addChild(c);
					layout_event.addChild(tc);
				}
			}
			
			JAnimation.initUI(matrix);
		}
		
		//fall - 下落结束
		private function fallOver(mc:MovieClip):Boolean{
			if(mc == null) return false;
			
			var p:Point = getPosition(mc);
			
			if(matrix[p.x][p.y + 1] == null && p.y < h - 1){
				matrix[p.x][p.y + 1] = mc;
				matrix[p.x][p.y] = null;
				
				return true;
			}
			return false;
		}
		
		//tmr - 每隔一段时间检测下系统:否要掉落，新建宝石，满足胜利,满足失败
		private function refreshSys():void{
			JPara.t_tips.text = JPara.jchapter.showTips();
			JPara.t_score.text = JPara.score + "";
			JPara.t_timer.text = JPara.timer + "";
			JPara.m_power.scaleX = JPara.power / JPara.POWER_LENGTH;
			
			//游戏胜利！
			if(JPara.jchapter.isWin()){
				JTimer.getInstance().timeStop();
				
				JPara.visited(JPara.currentCpt,JPara.stars);
				
				JStateAnimation.gameWin();
				JPara.jchapter.winSet();
				this.func_win();
				
				return;
			}
			
			//游戏失败！
			if(JPara.jchapter.isLose()){
				JTimer.getInstance().timeStop();
				JStateAnimation.shackAll(gameFail);
			}
			
			JPara.jchapter.run();
			
			//宝石掉落
			for(var x:int = 0 ; x < w ; x++){
				for(var y:int = h - 1 ; y > 0 ; y--){
					if(matrix[x][y] == null){
						var mc:MovieClip =this.getCrystal(x , y - 1);
						if(mc != null){
							matrix[x][y] = mc;
							matrix[x][y - 1] = null;
							
							JAnimation.fallDownCrystal(mc,fallOver);
							break;
						}
					}
				}
				
				//宝石新建
				if(matrix[x][0] == null){
					var c:MovieClip = JCrystal.getCrystal(JAlgorithm.randomCrystal(JPara.crystalNum));
					
					c.scaleX = scale;
					c.scaleY = scale;
					c.x = x * des + des/2;
					c.y = - des/2;
					
					matrix[x][0] = c;
					layout_crystal.addChild(c);
					JAnimation.fallDownCrystal(c,fallOver);
				}
			}
			
			//看看是不是需要刷新呢？
			var needGetRefresh:Boolean = true;
			for(x = 0 ; x < w ; x++){
				for(y = 0 ; y < h ; y++){
					mc =this.getCrystal(x , y);
					if(mc == null){
						needGetRefresh = false;
						hasRefreshed = false;
						
						x = w;
						y = h;
						break;
					}
				}
			}
			if(needGetRefresh){
				if(!hasRefreshed){
					hasRefreshed = true;
					var p:Point = JAlgorithm.getRemovableCrystal();
					if(p == null){
						/*for(x = 0 ; x < w ; x++){
							for(y = 0 ; y < h ; y++){
								matrix[x][y] = null;
							}
						}*/
						
						refreshTheMatrix();
					}
				}
			}
		}
		
		//sys - 刷新界面
		private function refreshTheMatrix():void{
			JStateAnimation.smallAll();
			
			var cm:Array = JAlgorithm.getMatrix(w,h,JPara.crystalNum);
			matrix = new Array();
			
			for(var x:int = 0 ; x < w ; x++){
				matrix[x] = new Array();
				for(var y:int = 0 ; y < h ; y++){
					matrix[x][y] = null;
					var c:MovieClip = JCrystal.getCrystal(cm[x][y]);
					c.scaleX = scale;
					c.scaleY = scale;
					c.x = x * des + des/2;
					c.y = y * des + des/2;
		
					c.alpha = 0;
		
					matrix[x][y] = c;
					layout_crystal.addChild(c);
				}
			}
			//--end for
			JAnimation.initUI(matrix);
		}
		
		//sys - 游戏失败
		private function gameFail():void{
			this.func_fail();
		}
		
		//sys - 检查是否还有需要自动消除的水晶
		public function checkSys():void{
			for(var x:int = 0 ; x < w ; x++){
				for(var y:int = 0 ; y < h ; y++){
					var ary:Array = JAlgorithm.getDelete(x,y);
					
					if(ary.length != 0){
						JPara.addCrystal(ary);
						
						JPara.addPower(ary.length);
						JPara.addScore(ary.length);
						
						for(var i:int = 0 ; i < ary.length ; i++){
							var jd:JDelete = JDelete(ary[i]);
					
							for(var j:int = 0 ; j < jd.points.length ; j++){
								var p:Point = Point(jd.points[j]);
								var c:MovieClip = getCrystal(p.x,p.y);
								JAnimation.deleteCrystal(c,deleteCrystal);
							}
						}
						
						JTimer.getInstance().refreshComboTime();
					}
				}
			}
		}
		
		//ex - 鼠标按下
		private function cclick(e:MouseEvent):void{
			if(getTarget(e) == null) return;
			
			mouseIsDown = true;
			
			for (var x:int = 0; x < w; x++)
			{
				for (var y:int = 0; y < h; y++)
				{
					var tmc:MovieClip = MovieClip(matrix[x][y]);
					if(tmc != null) tmc.gotoAndStop(1);
				}
			}
			
			var mc:MovieClip = getTarget(e);
			var tg:MovieClip = getCrystal(mc.xx,mc.yy);
			
			if(tg == null) return;
			
			if(target != null && target != tg){
				var p:Point = getPosition(target);
				
				if(p != null){
					if(Math.abs(p.x - mc.xx) + Math.abs(p.y - mc.yy) == 1 && 
						target.sta == JCrystal.STATE_NORMAL &&  tg.sta == JCrystal.STATE_NORMAL){
						mouseIsDown = false;
						JAnimation.exchangeCrystal(target,tg,exchangePosition);
						target = null;
					}else{
						if(tg.sta == JCrystal.STATE_NORMAL){
							tg.play();
							target = tg;
						}
					}
				}else{
					target = tg;
				}
			}else if(target == tg && target != null){
				target = null;
			}else{
				if(tg.sta == JCrystal.STATE_NORMAL){
					tg.play();
					target = tg;
				}
			}
			
			if(e.target == null || e.relatedObject != null){
				tg.gotoAndStop(1);
				target = null;
			}
		}
		
		//ex - 鼠标释放
		private function cup(e:MouseEvent):void{
			mouseIsDown = false;
		}
		
		//ex - 鼠标移出
		private function cout(e:MouseEvent):void{
			if(!mouseIsDown) return;
			
			var mc:MovieClip =getTarget(e);
			var tg:MovieClip = getCrystal(mc.xx,mc.yy);
			
			target = tg;
			//if(tg == target){
				var tmc:MovieClip = null;
				
				if(e.localY <= 0){
					tmc = getBac(mc.xx,mc.yy - 1);
				}else if(e.localX <= 0){
					tmc = getBac(mc.xx - 1,mc.yy);
				}else if(e.localY >= BAC_DES){
					tmc = getBac(mc.xx,mc.yy + 1);
				}else if(e.localX >= BAC_DES){
					tmc = getBac(mc.xx + 1,mc.yy);
				}
				var ee:MouseEvent = new MouseEvent(MouseEvent.CLICK,true,false,0,0,tmc);
				cclick(ee);
			//}
		}
		
		//func - 玩家点击放大镜提示
		private function clickSearch(e:MouseEvent):void{
			if(JPara.m_search.t_num.text <= 0) return;
			
			var p:Point = JAlgorithm.getRemovableCrystal();
			if(p != null){
				JPara.m_search.t_num.text--;
				var mc:MovieClip = this.getCrystal(p.x,p.y);
				JAnimation.showTip(mc,null);
			}
		}
		
		//func - 玩家点击刷新
		private function clickRefresh(e:MouseEvent):void{
			if(JPara.m_refresh.t_num.text <= 0) return;
			JPara.m_refresh.t_num.text--;
			refreshTheMatrix();
		}
		
		//func - ex - 获取鼠标事件传递的target对象
		private function getTarget(e:MouseEvent):MovieClip{
			if(e.target != null){
				return MovieClip(e.target);
			}else{
				return MovieClip(e.relatedObject);
			}
			return null;
		}
		
		//func - de - 删除水晶
		public function deleteCrystal(mc:MovieClip):void{
			var p:Point = getPosition(mc);
			matrix[p.x][p.y] = null;
			layout_crystal.removeChild(mc);
		}
		
		//func -ex - 玩家交换水晶（需要判断）
		private function exchangePosition(mc1:MovieClip,mc2:MovieClip):void{
			exchangePositionInfo(mc1,mc2);
			
			var p1:Point = getPosition(mc1);
			var p2:Point = getPosition(mc2);
			
			var ary1:Array = JAlgorithm.getDelete(p1.x,p1.y);
			var ary2:Array = JAlgorithm.getDelete(p2.x,p2.y);
			var ary:Array = ary1.concat(ary2);
			
			if(ary.length != 0){
				JPara.addCrystal(ary1);
				JPara.addCrystal(ary2);
				
				JPara.addPower((ary1.length + ary2.length)*2);
				JPara.addScore((ary1.length + ary2.length));
			
				if(JTimer.getInstance().isCombo(JPara.getComboTime())){
					JPara.combo++;
					JPara.addPower(JPara.combo > 10 ? 5 : JPara.combo / 2);
					
					if(ary1.length != 0){
						JAnimation.showCombo(mc1,JPara.combo,null);
					}else{
						JAnimation.showCombo(mc2,JPara.combo,null);
					}
					
				}else{
					JPara.combo = 0;
				}
				
				for(var i:int = 0 ; i < ary.length ; i++){
					var jd:JDelete = JDelete(ary[i]);
					
					for(var j:int = 0 ; j < jd.points.length ; j++){
						var p:Point = Point(jd.points[j]);
						
						var c:MovieClip = getCrystal(p.x,p.y);
						JAnimation.deleteCrystal(c,deleteCrystal);
					}
				}
			}else{
				JAnimation.exchangeCrystal(mc1,mc2,exchangeBack);
			}
		}
		
		//func -ex - 交换返回
		private function exchangeBack(mc1:MovieClip,mc2:MovieClip):void{
			exchangePositionInfo(mc1,mc2);
			
			checkSys();
		}
		
		//func - ex - 交换对应矩阵水晶信息
		private function exchangePositionInfo(mc1:MovieClip,mc2:MovieClip):void{
			var p1:Point = getPosition(mc1);
			var p2:Point = getPosition(mc2);
			
			matrix[p1.x][p1.y] = mc2;
			matrix[p2.x][p2.y] = mc1;
			
			mc1.sta = JCrystal.STATE_NORMAL;
			mc2.sta = JCrystal.STATE_NORMAL;
			
			//setTop(getBac(p2.x,p2.y),mc1);
			//setTop(getBac(p1.x,p1.y),mc2);
		}
		
		//func - ex - 获取水晶对应矩阵位置
		private function getPosition(mc:MovieClip):Point{
			for (var x:int = 0; x < w; x++)
			{
				for (var y:int = 0; y < h; y++)
				{
					if(matrix[x][y] == mc){
						return new Point(x,y);
					}
				}
			}
			
			return null;
		}
		
		//func - ex - 获取对应坐标的水晶（如果是normal，特定状态则不能获取）
		public function getCrystal(xx:int,yy:int,normal:Boolean = true):MovieClip{
			if(xx<0 || yy<0 || xx>=w || yy>= h){
				return null;
			}
			
			var tg:MovieClip = MovieClip(matrix[xx][yy]);
			if(tg == null) return null;
			if(tg.sta == JCrystal.STATE_NORMAL || !normal){
				return tg;
			}
			return null;
		}
		
		//func - ex - 将判定器置顶
		private function setTop(top:MovieClip,end:MovieClip):void{
			var td:int = JPara.stage.getChildIndex(top);
			var ed:int = JPara.stage.getChildIndex(end);
			
			if(td < ed){
				JPara.stage.setChildIndex(top,ed);
				JPara.stage.setChildIndex(end,td);
			}
		}
		
		//func - ex - 全部置顶
		private function setAllTop():void{
			for(var i:int = 0 ; i < bacs.length ; i++){
				var c:MovieClip = MovieClip(bacs[i]);
				JPara.stage.setChildIndex(c,JPara.stage.numChildren - 1);
			}
		}
		
		//func - hit - 不能点击
		public function noHit():void{
			this.layout_event.scaleX = 0;
		}
		
		//func - hit - 可以点击
		public function goHit():void{
			this.layout_event.scaleX = 1;
		}
		
		//func - ex - 获取判定器
		private function getBac(xx:int,yy:int):MovieClip{
			for(var i:int = 0 ; i < bacs.length ; i++){
				var tmp:MovieClip = MovieClip(bacs[i]);
				
				if(tmp.xx == xx && tmp.yy == yy){
					return tmp;
				}
			}
			return null;
		}
		
		//init - 绘制背景
		private function drawBac():void{
			layout_bac = new MovieClip();
			JPara.stage.addChild(layout_bac);
			
			for (var x:int = 0; x < w; x++)
			{
				for (var y:int = 0; y < h; y++)
				{
					var c:MovieClip = new BacFill();
					c.width = des;
					c.height = des;
					c.x = x * des;
					c.y = y * des;
					c.gotoAndStop((x + y) % 2 + 1);
					
					c.xx = x;
					c.yy = y;
					
					//JPara.stage.addChild(c); 
					layout_bac.addChild(c);
				}
			}
		}
	}
}